package com.usac.arqui1.grupo2.proyecto1;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.UUID;

import com.usac.arqui1.grupo2.proyecto1.app.utilGlobals;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Toast;

public class Btt extends Activity {

	private static int DISCOVERY_REQUEST = 1;

	private Handler handler = new Handler();
	private ArrayList<BluetoothDevice> foundDevices = new ArrayList<BluetoothDevice>();
	private ArrayAdapter<BluetoothDevice> aa;
	private ListView list;

	private BluetoothAdapter bluetooth;
	private BluetoothSocket socket;
	
	private UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_btt);
		// Inicializa la configuración Bluetooth
		configureBluetooth();
		setupListView();
		setupSearchButton();
		setupListenButton();
		setupBotonApagar();
	}

	/**
	 * Inicializa el bluetooth adapter, que sirve para controlar el bluetooth en general
	 */
	private void configureBluetooth() {
		bluetooth = BluetoothAdapter.getDefaultAdapter();
	}

	/**
	 * Configura el boton de Encender el Bluetooth. (Solo le agrega el listener)
	 */
	private void setupListenButton() {
		Button listenButton = (Button) findViewById(R.id.encenderBT);
		listenButton.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				Intent disc = new Intent(
						BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
				startActivityForResult(disc, DISCOVERY_REQUEST);
			}
		});
	}
	
	/**
	 * Configura el boton de apagar el bluetooth. (desconecta de Arduino)
	 */
	private void setupBotonApagar() {
		Button listenButton = (Button) findViewById(R.id.apagarBT);
		listenButton.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				bluetooth.disable();
			    Toast.makeText(getApplicationContext(), "Bluetooth Apagado", Toast.LENGTH_LONG)
			                    .show();
			}
		});
	}	
	
	//No se usa-----------
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == DISCOVERY_REQUEST) {
			boolean isDiscoverable = resultCode > 0;
			if (isDiscoverable) {
				String name = "bluetoothserver";
				try {
					final BluetoothServerSocket btserver = bluetooth
							.listenUsingRfcommWithServiceRecord(name, uuid);

					AsyncTask<Integer, Void, BluetoothSocket> acceptThread = new AsyncTask<Integer, Void, BluetoothSocket>() {

						@Override
						protected BluetoothSocket doInBackground(
								Integer... params) {
							try {
								socket = btserver.accept(params[0] * 1000);
								return socket;
							} catch (IOException e) {
								Log.d("BLUETOOTH", e.getMessage());
							}
							return null;
						}

						@Override
						protected void onPostExecute(BluetoothSocket result) {
							if (result != null)
								switchUI();
						}
					};
					acceptThread.execute(resultCode);
				} catch (IOException e) {
					Log.d("BLUETOOTH", e.getMessage());
				}
			}
		}
	}

	/**
	 * Se configura la ListView, almacena los dispositivos encontrados
	 * y además les agrega un listener a cada boton. Este listener selecciona el BluetoothDevice
	 * y luego crea un socket.
	 */
	private void setupListView() {
		aa = new ArrayAdapter<BluetoothDevice>(this,
				android.R.layout.simple_list_item_1, foundDevices);
 		list = (ListView) findViewById(R.id.list_discovered);
		list.setAdapter(aa);

		list.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> arg0, View view, int index,
					long arg3) {
				AsyncTask<Integer, Void, Void> connectTask = new AsyncTask<Integer, Void, Void>() {
					@Override
					protected Void doInBackground(Integer... params) {
						try {
							//TODO Esto va a la clase Global
							BluetoothDevice device = foundDevices
									.get(params[0]);
							
							final utilGlobals globalVariable = (utilGlobals) getApplicationContext();
							globalVariable.setD(device);
							
							//-----------------------------
							Method m = device.getClass().getMethod(
									"createRfcommSocket",
									new Class[] { int.class });
							socket = (BluetoothSocket) m.invoke(device, 1);
							// ---
							socket.connect();													
						} catch (IOException e) {
							Log.d("BLUETOOTH_CLIENT", e.getMessage());
						} catch (NoSuchMethodException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IllegalArgumentException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						return null;
					}

					@Override
					protected void onPostExecute(Void result) {
						switchUI();
					}
				};
				connectTask.execute(index);
			}
		});
	}

	/**
	 * Configura el boton de busqueda. Al presionarlo busca los dispositivos asosciados
	 * y los lista.
	 */
	private void setupSearchButton() {
		Button searchButton = (Button) findViewById(R.id.button_search);

		searchButton.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				registerReceiver(discoveryResult, new IntentFilter(
						BluetoothDevice.ACTION_FOUND));

				if (!bluetooth.isDiscovering()) {
					foundDevices.clear();
					bluetooth.startDiscovery();
				}
			}
		});
	}

	/**
	 * No sirve para nada, más que para hacer pruebas :P
	 */
	private void switchUI() {
		final EditText textEntry = (EditText) findViewById(R.id.text_message);
		list.setVisibility(View.GONE);
		textEntry.setEnabled(true);
		textEntry.setOnKeyListener(new OnKeyListener() {
			public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
				if ((keyEvent.getAction() == KeyEvent.ACTION_DOWN)
						&& (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
					sendMessage(socket, textEntry.getText().toString());
					textEntry.setText("");
					return true;
				}
				return false;
			}
		});
	}

	/**
	 * El Metodo mas importante, éste envía el mensaje indicando por donde (el socket) y el mensaje a enviar.
	 * @param socket Socket de comunicación ya habilidado.
	 * @param msg Mensaje que se enviará al Arduino.
	 */
	private void sendMessage(BluetoothSocket socket, String msg) {
		OutputStream outStream;
		try {
			outStream = socket.getOutputStream();
			byte[] byteString = (msg + " ").getBytes();
			byteString[byteString.length - 1] = 0;
			outStream.write(byteString);
		} catch (IOException e) {
			Log.d("BLUETOOTH_COMMS", e.getMessage());
		}
	}

	//------
	BroadcastReceiver discoveryResult = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			BluetoothDevice remoteDevice;
			remoteDevice = intent
					.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
			if (bluetooth.getBondedDevices().contains(remoteDevice)) {
				foundDevices.add(remoteDevice);
				aa.notifyDataSetChanged();
			}
		}
	};
}